﻿using LibGit2Sharp;
using OfficeOpenXml;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace codeCounter
{
    public partial class MainPage : ContentPage, INotifyPropertyChanged
    {
        private string _repoPath;
        private string _baseCommitId;
        private string _targetCommitId;
        private string _outputFolder;
        private ObservableCollection<string> _logMessages = new ObservableCollection<string>();
        private string _lastGeneratedFile;

        public string RepoPath
        {
            get => _repoPath;
            set
            {
                _repoPath = value;
                OnPropertyChanged();
                Preferences.Set("RepoPath", value);
            }
        }


        public string BaseCommitId
        {
            get => _baseCommitId;
            set
            {
                _baseCommitId = value;
                OnPropertyChanged();
            }
        }

        public string TargetCommitId
        {
            get => _targetCommitId;
            set
            {
                _targetCommitId = value;
                OnPropertyChanged();
            }
        }

        public string OutputFolder
        {
            get => _outputFolder;
            set
            {
                _outputFolder = value;
                OnPropertyChanged();
                Preferences.Set("OutputFolder", value);
            }
        }

        public ObservableCollection<string> LogMessages
        {
            get => _logMessages;
            set
            {
                _logMessages = value;
                OnPropertyChanged();
            }
        }

        public string LastGeneratedFile
        {
            get => _lastGeneratedFile;
            set
            {
                _lastGeneratedFile = value;
                OnPropertyChanged();
                // 当设置文件路径时调整窗口高度
                if (!string.IsNullOrEmpty(value))
                {
                    var window = Application.Current?.Windows[0];
                    if (window != null)
                    {
                        window.Height = 880; // 设置新的高度
                    }
                }
            }
        }

        public MainPage()
        {
            InitializeComponent();
            BindingContext = this;

            // 加载保存的路径
            RepoPath = Preferences.Get("RepoPath", string.Empty);
            OutputFolder = Preferences.Get("OutputFolder",
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GitCodeStats"));


            LogMessage("应用程序已启动");
        }

        private async void OnAnalyzeClicked(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(RepoPath))
            {
                await DisplayAlert("错误", "请输入有效的仓库路径", "确定");
                return;
            }

            if (!Directory.Exists(RepoPath))
            {
                await DisplayAlert("错误", "仓库路径不存在", "确定");
                return;
            }

            if (string.IsNullOrWhiteSpace(BaseCommitId) || string.IsNullOrWhiteSpace(TargetCommitId))
            {
                await DisplayAlert("错误", "请输入有效的提交ID", "确定");
                return;
            }

            if (string.IsNullOrWhiteSpace(OutputFolder))
            {
                OutputFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                    "GitCodeStats");
            }

            // 确保输出文件夹存在
            if (!Directory.Exists(OutputFolder))
            {
                Directory.CreateDirectory(OutputFolder);
                LogMessage($"创建输出目录: {OutputFolder}");
            }

            try
            {
                // 设置按钮状态为忙碌
                analyzeButton.IsEnabled = false;

                // 使用Task.Run在后台线程执行耗时操作
                await Task.Run(() =>
                {
                    LogMessage("开始分析代码变更...");

                    // 创建输出文件名
                    string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                    string excelPath = Path.Combine(OutputFolder, $"代码统计_{timestamp}.xlsx");

                    // 分析提交差异
                    var results = AnalyzeCommitDifferences(RepoPath, BaseCommitId, TargetCommitId);

                    // 导出到Excel
                    ExportToExcel(results, excelPath);

                    // 更新最后生成的文件
                    MainThread.BeginInvokeOnMainThread(() =>
                    {
                        LastGeneratedFile = excelPath;
                        LogMessage($"分析完成，结果已保存到: {excelPath}");
                        // // 调整窗口高度
                        // var window = Application.Current?.Windows[0];
                        // if (window != null)
                        // {
                        //     window.Height = 860; // 调整为新的高度
                        // }

                        // 分析完成后清空提交ID
                        BaseCommitId = string.Empty;
                        TargetCommitId = string.Empty;
                    });
                });
            }
            catch (Exception ex)
            {
                LogMessage($"发生错误: {ex.Message}");
                await DisplayAlert("错误", ex.Message, "确定");
            }
            finally
            {
                // 恢复按钮状态
                analyzeButton.IsEnabled = true;
            }
        }

        private async void OnValidateRepoPathClicked(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(RepoPath))
            {
                await DisplayAlert("错误", "请输入仓库路径", "确定");
                return;
            }

            if (!Directory.Exists(RepoPath))
            {
                await DisplayAlert("错误", "指定的仓库路径不存在", "确定");
                return;
            }

            // 检查是否是有效的Git仓库
            try
            {
                using (var repo = new LibGit2Sharp.Repository(RepoPath))
                {
                    await DisplayAlert("成功", "仓库路径有效", "确定");
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("错误", $"指定的路径不是有效的Git仓库: {ex.Message}", "确定");
            }
        }

        private async void OnValidateOutputPathClicked(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(OutputFolder))
            {
                await DisplayAlert("错误", "请输入输出目录路径", "确定");
                return;
            }

            if (!Directory.Exists(OutputFolder))
            {
                var result = await DisplayAlert("提示", "输出目录不存在，是否创建?", "是", "否");
                if (result)
                {
                    try
                    {
                        Directory.CreateDirectory(OutputFolder);
                        await DisplayAlert("成功", "输出目录已创建", "确定");
                    }
                    catch (Exception ex)
                    {
                        await DisplayAlert("错误", $"无法创建输出目录: {ex.Message}", "确定");
                    }
                }
            }
            else
            {
                await DisplayAlert("成功", "输出目录有效", "确定");
            }
        }

        private async void OnOpenOutputFolderClicked(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(OutputFolder) && Directory.Exists(OutputFolder))
            {
                try
                {
                    // 尝试打开输出文件夹
                    await Launcher.OpenAsync(new Uri($"file://{OutputFolder}"));
                }
                catch (Exception ex)
                {
                    await DisplayAlert("错误", $"无法打开输出文件夹: {ex.Message}", "确定");
                }
            }
            else
            {
                await DisplayAlert("信息", "输出文件夹不存在", "确定");
            }
        }

        private void LogMessage(string message)
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                LogMessages.Add($"[{DateTime.Now:HH:mm:ss}] {message}");

                // 改进的滚动逻辑
                try
                {
                    if (logListView != null && LogMessages.Count > 0)
                    {
                        // 使用延迟滚动，等待UI刷新
                        Device.BeginInvokeOnMainThread(async () =>
                        {
                            await Task.Delay(50); // 简短延迟让UI刷新
                            // 使用最后一个元素作为目标
                            var lastItem = LogMessages[LogMessages.Count - 1];
                            logListView.ScrollTo(lastItem, ScrollToPosition.End, false);
                        });
                    }
                }
                catch (Exception ex)
                {
                    // 避免因滚动失败而影响正常操作
                    Console.WriteLine($"滚动日志失败: {ex.Message}");
                }
            });
        }


        //核心代码 - 比较差异
        class FileChangeInfo
        {
            public string FilePath { get; set; }
            public int ChangedLines { get; set; }
            public string ChangeType { get; set; } // "新增" 或 "修改"
        }

        List<FileChangeInfo> AnalyzeCommitDifferences(string repoPath, string baseCommitId, string targetCommitId)
        {
            var results = new List<FileChangeInfo>();

            using (var repo = new Repository(repoPath))
            {
                // 获取指定的提交
                var baseCommit = repo.Lookup<Commit>(baseCommitId);
                var targetCommit = repo.Lookup<Commit>(targetCommitId);

                if (baseCommit == null)
                {
                    throw new Exception($"找不到提交ID: {baseCommitId}");
                }

                if (targetCommit == null)
                {
                    throw new Exception($"找不到提交ID: {targetCommitId}");
                }

                LogMessage($"比较提交: {baseCommit.MessageShort} -> {targetCommit.MessageShort}");

                // 获取两个提交之间的差异
                var changes = repo.Diff.Compare<TreeChanges>(baseCommit.Tree, targetCommit.Tree);
                LogMessage($"找到 {changes.Count()} 个文件变更");

                int processedCount = 0;
                foreach (var change in changes)
                {
                    processedCount++;
                    if (processedCount % 10 == 0)
                    {
                        LogMessage($"已处理 {processedCount}/{changes.Count()} 个文件");
                    }

                    string filePath = change.Path;

                    // 添加过滤条件，特定扩展名的文件
                    if (ShouldProcessFile(filePath))
                    {
                        string changeType;
                        int changedLines = 0;

                        if (change.Status == ChangeKind.Added)
                        {
                            // 新增文件，统计所有代码行
                            changeType = "新規";
                            var blob = targetCommit[filePath].Target as Blob;
                            string content = blob.GetContentText();
                            changedLines = CountCodeLines(content, Path.GetExtension(filePath));
                        }
                        else if (change.Status == ChangeKind.Modified)
                        {
                            // 修改文件，统计差异代码行
                            changeType = "修正";
                            // 获取文件内容差异
                            var patch = repo.Diff.Compare<Patch>(baseCommit.Tree, targetCommit.Tree,
                                new[] { filePath });
                            changedLines = CountChangedLines(patch, Path.GetExtension(filePath));
                        }
                        else
                        {
                            // 跳过删除的文件或其他类型
                            continue;
                        }

                        results.Add(new FileChangeInfo
                        {
                            FilePath = filePath,
                            ChangedLines = changedLines,
                            ChangeType = changeType
                        });
                    }
                }
            }

            LogMessage($"有效变更文件数: {results.Count}");
            return results;
        }

        int CountChangedLines(Patch patch, string fileExtension)
        {
            int changedLines = 0;

            foreach (var change in patch)
            {
                foreach (var line in change.AddedLines)
                {
                    string content = line.Content.Trim();

                    // 空行
                    if (string.IsNullOrWhiteSpace(content))
                        continue;

                    // 注释行
                    if (content.StartsWith("//") || content.StartsWith("/*") || content.StartsWith("*"))
                        continue;

                    // HTML 注释
                    if (content.StartsWith("<!--") || content.Contains("-->"))
                        continue;

                    changedLines++;
                }
            }

            return changedLines;
        }

        bool ShouldProcessFile(string filePath)
        {
            // 根据扩展名决定是否处理该文件
            string[] validExtensions =
            {
                ".js", ".properties", ".html", ".css", ".java", ".yml", ".sh", ".gradle", ".bat", ".xml", ".sql",
                ".json", ".utf8"
            };
            return validExtensions.Contains(Path.GetExtension(filePath).ToLower());
        }

        int CountCodeLines(string content, string fileExtension)
        {
            // 按行分割内容
            string[] lines = content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
            int codeLines = 0;
            bool inMultiLineComment = false;

            foreach (var line in lines)
            {
                string trimmedLine = line.Trim();

                // 空行
                if (string.IsNullOrWhiteSpace(trimmedLine))
                    continue;

                // 处理多行注释
                if (inMultiLineComment)
                {
                    if (trimmedLine.Contains("*/"))
                        inMultiLineComment = false;
                    continue;
                }

                // C#, Java, C++, JavaScript 风格的注释
                if (trimmedLine.StartsWith("//"))
                    continue;

                // 多行注释开始
                if (trimmedLine.StartsWith("/*"))
                {
                    inMultiLineComment = !trimmedLine.Contains("*/");
                    continue;
                }

                // HTML 风格的注释
                if (trimmedLine.StartsWith("<!--"))
                {
                    if (trimmedLine.Contains("-->"))
                    {
                        // 单行HTML注释，跳过
                        continue;
                    }
                    else
                    {
                        // 多行HTML注释开始
                        inMultiLineComment = true;
                        continue;
                    }
                }

                // 处理HTML多行注释结束
                if (trimmedLine.Contains("-->"))
                {
                    inMultiLineComment = false;
                    continue;
                }

                codeLines++;
            }

            return codeLines;
        }

        void ExportToExcel(List<FileChangeInfo> results, string excelPath)
        {
            using (var package = new ExcelPackage())
            {
                var worksheet = package.Workbook.Worksheets.Add("代码行数统计");

                // 添加标题行
                worksheet.Cells[1, 1].Value = "文件路径";
                worksheet.Cells[1, 2].Value = "代码行数";
                worksheet.Cells[1, 3].Value = "变更类型";

                // 设置标题行样式
                var headerRange = worksheet.Cells[1, 1, 1, 3];
                headerRange.Style.Font.Bold = true;
                headerRange.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
                headerRange.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray);

                // 添加数据
                int row = 2;
                foreach (var result in results)
                {
                    string displayPath = result.FilePath;
                    if (displayPath.StartsWith("Aegis-src/"))
                    {
                        displayPath = displayPath.Substring("Aegis-src/".Length);
                    }
                    worksheet.Cells[row, 1].Value = displayPath;
                    worksheet.Cells[row, 2].Value = result.ChangedLines;
                    worksheet.Cells[row, 3].Value = result.ChangeType;

                    row++;
                }

                // 统计总行数
                int totalLines = results.Sum(r => r.ChangedLines);
                int newFiles = results.Count(r => r.ChangeType == "新規");
                int modifiedFiles = results.Count(r => r.ChangeType == "修正");

                // 添加摘要信息
                row++;
                worksheet.Cells[row, 1].Value = "总计";
                worksheet.Cells[row, 3].Value = totalLines;
                worksheet.Cells[row, 1].Style.Font.Bold = true;
                worksheet.Cells[row, 3].Style.Font.Bold = true;

                row++;
                worksheet.Cells[row, 1].Value = "新增文件数";
                worksheet.Cells[row, 3].Value = newFiles;

                row++;
                worksheet.Cells[row, 1].Value = "修改文件数";
                worksheet.Cells[row, 3].Value = modifiedFiles;

                // 自动调整列宽
                worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();

                // 保存Excel文件
                package.SaveAs(new FileInfo(excelPath));
            }
        }
    }
    
}